<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>3D Tiles Loader: RealityCapture</title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }
    body {
      width: 100vw;
      height: 100vh;
      overflow: hidden;
    }
    #canvas-parent {
      width: 100vw;
      height: 100vh;
      touch-action: none;
    }
    #guide {
      position: fixed;
      top: 0;
      right: 0;
      width: 300px;
      padding: 1rem 2rem;
      font-family:'Courier New', Courier, monospace;
      line-height: 1.2;
      background-color: white;
      color: black;
    }

    #guide p {
      margin-top: 10px;
    }

    #stats-widget  {
      position: fixed;
      top: 70px;
      padding: 10px;
    }
    #stats-widget div {
      width: 300px;
      word-break: break-all;
    }
    #button {
      position: fixed;
      bottom: 16px;
      right: 16px;
      padding: 12px;
      border-radius: 50%;
      margin-bottom: 0px;
      background-color: #FFF;
      opacity: .9;
      z-index: 999;
      box-shadow: 0 0 4px rgb(0 0 0 / 15%);
    }
    @media (max-width:480px) {
      #guide, #stats-widget { display: none; }
    }
  </style>
</head>
<body>
  <div id='canvas-parent'></div>
  <div id="stats-widget"></div>

  <div id="guide">
    <span id="example-desc">
      <b>Freeman Alley, New York.</b> Captured using iPhone 12 Pro Max and processed via RealityCapture.
    </span>
    <p>Use arrow/WASD keys or mouse wheel/trackpad to move around, and click and drag to turn/rotate the camera.</p>
    <p>
      <u>Available URL parameters:</u>
      <ul>
        <li><b>tilesetUrl</b>: Load another tileset json.</li>
        <li><b>sse</b>: Change the maximum screen space error.</li>
      </ul>
    </p>
  </div>

  <script type='module'>
    import { 
      Scene, 
      PerspectiveCamera, 
      WebGLRenderer, 
      Clock,
      Matrix4,
      Vector2,
      Euler,
      SRGBColorSpace,
    } from 'three';

    import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';

    import { Loader3DTiles } from '../../../src/index.ts';

    import { CameraRig, FreeMovementControls } from 'three-story-controls'

    import Stats from 'three/examples/jsm/libs/stats.module.js';
    import StatsWidget from '@probe.gl/stats-widget';

    const queryParams = new URLSearchParams(document.location.search);

    const canvasParent = document.querySelector('#canvas-parent');
    const statsParent = document.querySelector('#stats-widget')

    const scene = new Scene();
    const camera = new PerspectiveCamera(
      35,
      1,
      0.01,
      1000,
    );

    const viewportSize = new Vector2();
    const renderer = new WebGLRenderer();
    renderer.outputColorSSpace = SRGBColorSpace;

    const clock = new Clock()
    const rig = new CameraRig(camera, scene)
    
    let controls = undefined;

    if (queryParams.get('orbit')) {
      controls = new OrbitControls( camera, canvasParent);
      controls.listenToKeyEvents( document.body );
      camera.position.set(0,200,0);
      controls.update();
    } else {
      controls = new FreeMovementControls(rig, {
        panDegreeFactor: 2,
        wheelScaleFactor: 0.01,
        keyboardScaleFactor: 0.015,
        keyboardDampFactor: 0
      });
      controls.enable();
    }
    
    canvasParent.appendChild(renderer.domElement);

    const threeJsStats = new Stats();
    threeJsStats.domElement.style.position = 'absolute';
    threeJsStats.domElement.style.top = '10px';
    threeJsStats.domElement.style.left = '10px';

    canvasParent.appendChild( threeJsStats.domElement );


    let tilesRuntime = undefined;
    let statsRuntime = undefined;

    if (queryParams.get('tilesetUrl')) {
      document.querySelector('#example-desc').style.display = 'none';
    }

   loadTileset();

    async function loadTileset() {
      const result = await Loader3DTiles.load(
        {
          url:
            queryParams.get('tilesetUrl') ??
           'https://int.nyt.com/data/3dscenes/ONA360/TILESET/0731_FREEMAN_ALLEY_10M_A_36x8K__10K-PN_50P_DB/tileset_tileset.json',
           viewport: getViewport(),
          options: {
            dracoDecoderPath: 'https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/draco',
            basisTranscoderPath: 'https://cdn.jsdelivr.net/npm/three@0.160.0/examples/jsm/libs/basis',
            maximumScreenSpaceError: queryParams.get('sse') ?? 48,
            resetTransform: true
          }
      });

      const {model, runtime} = result;
      model.rotation.set(-Math.PI / 2, 0, Math.PI / 2);

      if (!queryParams.get('tilesetUrl')) {
        model.position.set(-1, 4, -16);
      }

      tilesRuntime = runtime;
      scene.add(model);

      statsRuntime = new StatsWidget(runtime.getStats(), {container: statsParent });
      statsParent.style.visibility = 'visible';
    }

    function render(t) {
      const dt = clock.getDelta()
      controls.update(t);
      if (tilesRuntime) {
        tilesRuntime.update(dt, camera);
      }
      if (statsRuntime) {
        statsRuntime.update();
      }
      renderer.render(scene, camera);
      threeJsStats.update();
      window.requestAnimationFrame(render);

    }

    onWindowResize();

    function onWindowResize() {
      renderer.setSize(canvasParent.clientWidth, canvasParent.clientHeight);
      tilesRuntime?.setViewport(getViewport());
      camera.aspect = canvasParent.clientWidth / canvasParent.clientHeight;
      camera.updateProjectionMatrix();
    }
    window.addEventListener('resize', onWindowResize)

    function getViewport() {
      return {
        width: canvasParent.clientWidth,
        height: canvasParent.clientHeight,
        devicePixelRatio: window.devicePixelRatio
      }
    }

    render();
  </script>
  <a id="button" target="_blank" href="https://github.com/nytimes/three-loader-3dtiles/blob/master/examples/demos/realitycapture/index.html" title="View source code for demo" style=""><img src="../ic_code_black_24dp.svg"></a>
</body>
</html>
